/*
 * Copyright (c) 2020 hebeiyiliuba.com
 * All rights reserved.
 *
 */
package org.jeecg.modules.wlhy.etcfeeclouds.service;

import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.api.wlhy.etcfeeclouds.req.ApiEtcBaseReq;
import org.jeecg.modules.third.etc.feeclouds.constant.enums.ChannelEnum;
import org.jeecg.modules.third.etc.feeclouds.constant.enums.FeecloudsConstant;
import org.jeecg.modules.third.etc.feeclouds.utils.MD5Util;
import org.jeecg.modules.wlhy.utils.HyConfigUtils;
import org.jeecg.modules.wlhy.hyconfig.entity.HyConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * 在这里编写类的功能描述
 *
 * @author duanlikao
 * @created 2021/9/8
 */
@Service
public class EtcFeeCloudService {

    private static final Logger LOGGER = LoggerFactory.getLogger(EtcFeeCloudService.class);


    @Autowired
    private RedisUtil redisUtil;

    public void check(ChannelEnum channelEnum ,ApiEtcBaseReq apiEtcBaseReq ) {
        LOGGER.debug("EtcFeeCloudService check channelEnum :{} apiEtcBaseReq: {}", channelEnum, apiEtcBaseReq);
        if(StringUtils.isBlank(apiEtcBaseReq.getSign())){
            throw new JeecgBootException("签名不能为空！");
        }
        if(StringUtils.isBlank(apiEtcBaseReq.getRequestId())){
            throw new JeecgBootException("请求ID不能为空！");
        }

        if(StringUtils.isBlank(apiEtcBaseReq.getData())){
            throw new JeecgBootException("推送数据不能为空！");
        }
        String key =  MD5Util.md5(apiEtcBaseReq.getSign()+apiEtcBaseReq.getRequestId());
        String cacheKey =  FeecloudsConstant.API_TAX_SIGN_KEY(channelEnum.getCode() ,key);
        if (redisUtil.hasKey(cacheKey)) {
            throw new JeecgBootException("请不要重复推送！");
        }
        redisUtil.set(cacheKey, apiEtcBaseReq, FeecloudsConstant.API_TAX_SIGN_KEY_EXPIRE);
    }

    /**
     *
     * @param apiEtcBaseReq
     * @return
     */
    public String getSign(ApiEtcBaseReq apiEtcBaseReq){
        HyConfig systemConfig = HyConfigUtils.getConfig();
        if(systemConfig == null || !systemConfig.getEtcFeecloudsIzUse()){
            throw new JeecgBootException("路耕ETC上报服务暂未开启,请联系管理员。");
        }

        String stringSignTemp =  assembleParam( apiEtcBaseReq,  1, 1);
        if(StringUtils.isBlank(stringSignTemp)) {
            throw new JeecgBootException("签名参数为空！");
        }
        String key = MD5Util.md5(systemConfig.getEtcFeecloudsSecrect());
        String sign =  MD5Util.sha256Mac(stringSignTemp,key.toUpperCase());
        LOGGER.debug("EtcFeeCloudService getSign stringSignTemp :{} sign: {}", stringSignTemp, sign);
       return sign ;
    }



    /**
     * 1、把请求参数中除“signMsg”外的所有参数按key进行ASCII 码升序排列。
     * 2、再将排序后的参数键值对用&拼接起来(例key1=value1&key2=value2)。
     * 3、在对请求的参数做签名时，对于请求参数列表中那些可空的参数，如果选择使用它们，那么这些参数的参数值必须不能为空或空值。
     *
     * @param apiEtcBaseReq
     * @return
     */
    private String assembleParam(ApiEtcBaseReq apiEtcBaseReq, Integer linkFormatType, Integer sortEnumType) {

        Map <String, String> paramsMap = Maps.newHashMap();
        paramsMap.put("requestId", apiEtcBaseReq.getRequestId());
        paramsMap.put("timeStamp", apiEtcBaseReq.getTimeStamp());
        paramsMap.put("data",apiEtcBaseReq.getData() );
        //Arrays.asList((String) apiEtcBaseReq.getData()).stream().collect(Collectors.joining())
        TreeMap <String, String> sortabledMap = new TreeMap<>(
                (o1, o2) -> sortEnumType == 2 ? o2.compareTo(o1) : o1.compareTo(o2));
        paramsMap.forEach(sortabledMap::put);
        if (linkFormatType == 2) {
            StringBuilder sb = new StringBuilder();
            sortabledMap.forEach((key, val) -> {
                sb.append(val);
            });
            return sb.toString();
        } else if (linkFormatType == 1) {
            List <String> kvList = new ArrayList();
            sortabledMap.forEach((key, val) -> {
                kvList.add(key + "=" + val);
            });
            return join("&", kvList);
        } else {
            return StringUtils.EMPTY;
        }

    }

    public static String join(String join, List<String> listStr) {
        StringBuilder sb = new StringBuilder();
        int i = 0;

        for (int len = listStr.size(); i < len; ++i) {
            if (i == len - 1) {
                sb.append(listStr.get(i));
            } else {
                sb.append(listStr.get(i)).append(join);
            }
        }

        return sb.toString();
    }
}
